﻿#if defined(_WIN32) && !defined(__MINGW32__)
#include "souistd.h"
#include "SAxContainer.h"

SNSBEGIN

SAxContainer::SAxContainer()
    : m_lRefCnt(1)
{
}

SAxContainer::~SAxContainer()
{
}

BOOL SAxContainer::CreateControl(REFGUID clsid, DWORD dwClsCtx /*=CLSCTX_INPROC_SERVER*/)
{
    SASSERT(m_pAxHostDelegate);
    HRESULT hr = E_FAIL;
    SComPtr<IUnknown> pControl;
    hr = CoCreateInstance(clsid, NULL, dwClsCtx, __uuidof(IUnknown), reinterpret_cast<void **>(&pControl));
    if (SUCCEEDED(hr))
    {
        Init(pControl);
    }
    return SUCCEEDED(hr);
}

///////////////////////////////////////////////////////////////////////////////
// IUnknown
HRESULT SAxContainer::QueryInterface(REFIID iid, void **object)
{
    HRESULT hr = S_OK;
    *object = NULL;
    if (iid == IID_IUnknown)
    {
        // Avoid ambiguous resolution of IUnknown
        *object = static_cast<IUnknown *>(static_cast<MinimumIDispatchImpl *>(this));
    }
    else if (iid == IID_IDispatch)
    {
        *object = static_cast<MinimumIDispatchImpl *>(this);
    }
    else if (iid == IID_IOleContainer)
    {
        *object = static_cast<IOleContainer *>(this);
    }
    else if (iid == IID_IParseDisplayName)
    {
        *object = static_cast<IParseDisplayName *>(this);
    }
    else if (iid == IID_IBindHost)
    {
        *object = static_cast<IBindHost *>(this);
    }
    else if (iid == IID_IServiceProvider)
    {
        *object = static_cast<IServiceProvider *>(this);
    }
    else
    {
        hr = ActiveXSite::QueryInterface2(iid, object);
    }
    if (SUCCEEDED(hr))
    {
        static_cast<IUnknown *>(*object)->AddRef();
    }
    return hr;
}

ULONG STDMETHODCALLTYPE SAxContainer::AddRef()
{
    return ::InterlockedIncrement(&m_lRefCnt);
}

ULONG STDMETHODCALLTYPE SAxContainer::Release()
{
    // We don't destroy object when it reaches 0
    return ::InterlockedDecrement(&m_lRefCnt);
}

///////////////////////////////////////////////////////////////////////////////
// IBindHost
HRESULT SAxContainer::CreateMoniker(LPOLESTR szName, IBindCtx * /*pBC*/, IMoniker **ppmk, DWORD /*dwReserved*/)
{
    HRESULT hr;
    typedef HRESULT(WINAPI * pfnCreateURLMonikerEx)(IMoniker * pMkCtx, LPCWSTR szURL, IMoniker * *ppmk, DWORD dwFlags);
    HMODULE urlmon = ::GetModuleHandleA("urlmon.dll");
    if (!urlmon)
        urlmon = ::LoadLibraryA("urlmon.dll");
    pfnCreateURLMonikerEx OrigCreateURLMonikerEx = (pfnCreateURLMonikerEx)::GetProcAddress(urlmon, "CreateURLMonikerEx");
    hr = OrigCreateURLMonikerEx(NULL, szName, ppmk, URL_MK_UNIFORM);
    return hr;
}

HRESULT SAxContainer::MonikerBindToStorage(IMoniker *pMk, IBindCtx *pBC, IBindStatusCallback *pBSC, REFIID riid, void **ppvObj)
{
    HRESULT hr = E_FAIL;
    SComPtr<IBindCtx> pBCCtx = pBC;
    if (pBCCtx == NULL)
    {
        // creates it if not present
        hr = CreateBindCtx(0, &pBCCtx);
    }

    if (pBCCtx != NULL)
    {
        if (pBSC != NULL)
        {
            typedef HRESULT(WINAPI * pfnRegisterBindStatusCallback)(IBindCtx * pbc, IBindStatusCallback * pbsc, IBindStatusCallback * *ppbscPrevious, DWORD dwReserved);
            HMODULE urlmon = ::GetModuleHandleA("urlmon.dll");
            if (!urlmon)
                urlmon = ::LoadLibraryA("urlmon.dll");
            pfnRegisterBindStatusCallback OrigRegisterBindStatusCallback = (pfnRegisterBindStatusCallback)::GetProcAddress(urlmon, "RegisterBindStatusCallback");
            hr = OrigRegisterBindStatusCallback(pBCCtx, pBSC, NULL, 0);
        }
        hr = pMk->BindToStorage(pBCCtx, NULL, riid, ppvObj);
    }
    return hr;
}

HRESULT SAxContainer::MonikerBindToObject(IMoniker * /*pMk*/, IBindCtx * /*pBC*/, IBindStatusCallback * /*pBSC*/, REFIID /*riid*/, void ** /*ppvObj*/)
{
    ATLTRACENOTIMPL(_T("ActiveXContainerImpl::MonikerBindToObject\n"));
}

// {0002DF05-0000-0000-C000-000000000046}
static const GUID GUID_IWebBrowserApp = { 0x0002DF05, 0x0000, 0x0000, { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };

// {1B36028E-B491-4BB2-8584-8A9E0A677D6E}
static const GUID GUID_IXcpControlHost = { 0x1B36028E, 0xB491, 0x4BB2, { 0x85, 0x84, 0x8A, 0x9E, 0x0A, 0x67, 0x7D, 0x6E } };

HRESULT SAxContainer::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
{
    HRESULT hr = E_FAIL;
    if (guidService == IID_IBindHost || guidService == GUID_IWebBrowserApp || guidService == GUID_IXcpControlHost)
    {
        hr = QueryInterface(riid, ppvObject);
    }
    return hr;
}

SNSEND

#endif // defined(_WIN32) && !defined(__MINGW32__)